package main

import (
	"reflect"
	"fmt"
)

func main()  {

	//test1()

	//test2()

	//test3()

	test4()
}

func test1()  {

	str := "hello world"
	rValue := reflect.ValueOf(str)
	rType := reflect.TypeOf(str)

	fmt.Println(rValue)
	fmt.Println(rType)
	fmt.Println(rType.Name())
	fmt.Println(rType.String())

	fmt.Println(rType.Kind())
}

func test2()  {
	user := User{"李四", 18, "男"}

	t := reflect.TypeOf(user)
	v := reflect.ValueOf(user)

	fmt.Printf("%T   %T   %v    %v\n", user, t, user, t)
	fmt.Printf("%T   %T   %v    %v\n", user, v, user, v)

	fmt.Println("--------------------")
	fmt.Println(t.Kind())
	fmt.Println(t.String())			// 类的全路径名
	fmt.Println(t.Name())			// 类名
	fmt.Println(t.NumField())		//字段数量
	fmt.Println(t.NumMethod())		//方法数量

}

//获取所有 类型描述所有数据
func test3()  {
	user := User{"李四", 18, "男"}

	t := reflect.TypeOf(user)
	//v := reflect.ValueOf(user)

	fmt.Printf("%T   %T    %v   %v\n", user, t, user, t)

	fmt.Println("数据类型:", t.Kind())
	fmt.Println("结构体名:", t.Name())
	fmt.Println("结构体全路径名:", t.String())

	fmt.Println("===========字段=================")
	fmt.Println("字段数:", t.NumField())

	fmt.Println("\n第一个字段:", t.Field(0))
	fmt.Println("第一个字段名:", t.Field(0).Name)
	fmt.Println("第一个字段类型:", t.Field(0).Type, t.Field(0).Type.Kind() == reflect.String)

	fmt.Println("\n第二个字段:", t.Field(1))
	fmt.Println("第二个字段名:", t.Field(1).Name)
	fmt.Println("第二个字段类型:", t.Field(1).Type, t.Field(1).Type.Kind() == reflect.String)

	fmt.Println("\n第三个字段:", t.Field(2))
	fmt.Println("第三个字段名:", t.Field(2).Name)
	fmt.Println("第三个字段类型:", t.Field(2).Type, t.Field(2).Type.Kind() == reflect.String)


	fmt.Println("\n==========方法===================")
	fmt.Println("方法数:", t.NumMethod())

	fmt.Println("\n第一个方法:", t.Method(0))
	fmt.Println("第一个方法名:", t.Method(0).Name)
	fmt.Println("第一个方法类型:", t.Method(0).Type, t.Method(0).Type.Kind() == reflect.String)

	fmt.Println("\n第二个方法:", t.Method(1))
	fmt.Println("第二个方法名:", t.Method(1).Name)
	fmt.Println("第二个方法类型:", t.Method(1).Type, t.Method(1).Type.Kind() == reflect.String)


	fmt.Println("\n\n==============方法参数==========================")
	method := t.Method(0)
	fmt.Println(method.Index)
}


//测试 获取所有值
func test4()  {
	user := User{"李四", 18, "男"}

	t := reflect.TypeOf(user)
	v := reflect.ValueOf(user)

	fmt.Printf("%T   %T   %v    %v\n", user, v, user, v)

	fmt.Println("========================")
	fmt.Println(v.String())

	fmt.Println("===========字段===============")
	fmt.Println("字段数量", v.NumField())

	for i:=0; i<v.NumField(); i++ {
		fmt.Println("字段名：", v.Field(i).String())
		fmt.Println("字段类型:", v.Field(i).Kind(), v.Field(i).Kind() == reflect.String)

		switch v.Field(i).Kind() {
		case reflect.String:
			fmt.Println("--1字段值:", v.Field(i).String())
		case reflect.Int:
			fmt.Println("--2字段值:", v.Field(i).Int())
		default:
			fmt.Println("--3其他类型")

		}
		fmt.Println("--------------")
	}



	fmt.Println("\n\n===========方法============")
	fmt.Println("方法数量:", v.NumMethod())

	for i:=0; i<v.NumMethod(); i++ {
		method := v.Method(i)
		fmt.Println("-----------------方法类型:", method.Type().Kind(), method.Type().Kind() == reflect.Func)
		fmt.Println("方法类型:", method.Type())

		fmt.Println("方法名:", t.Method(i).Name)
		fmt.Println("入参个数:", method.Type().NumIn())
		fmt.Println("入参个数--:", t.Method(i).Type.NumIn())
		fmt.Println("出参个数:", method.Type().NumOut())
		fmt.Println("出参个数--:", t.Method(i).Type.NumOut())

		fmt.Println("==入参")
		for j:=0; j<t.Method(i).Type.NumIn(); j++ {
			arg := t.Method(i).Type.In(j)
			fmt.Println("入参",j, ":",arg.Kind(), arg.Name() )
		}

		fmt.Println("==出参")
		for j:=0; j<t.Method(i).Type.NumOut(); j++ {
			arg := t.Method(i).Type.Out(j)
			fmt.Println("出参", j, ":", arg.Kind(), arg.Name() )
		}
	}


}


type User struct {
	Name 	string
	Age 	int
	Sex		string
}

func (user User) Say(msg string, b bool) error {
	fmt.Println("say:", msg)
	return nil
}

func (user User) Study(msg string) (float64, error) {
	fmt.Println("say:", msg)
	return 1.1, nil
}